Reduce allocations: don't create unnecessary HashMaps and Strings
#133
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
For me, the
rust_i18n::i18n!macro created tens of thousands of hashmaps, and allocated tens of thousands of strings. Both of which were unnecessary. This was such a problem, that it caused stack overflows (on Windows only). This PR makes 2 optimizations:HashMaps are created: from one for every pair, to one for every language. Bringing the amount of HashMaps created from 14,000 to 32Strings are created from&'static strby usingCow<'static, str>Optimization 1: Don't create so many hashmaps. The expansion of
i18n!creates aHashMapfor every translation pair. I have a lot of translations, so for me thousands of translations were being created. CreatingHashMapis expensive, there's no reason to do it once for every pairIn this PR Ive changed the expansion so only a single HashMap is created per language. That brings up the count of HashMap from thousands to a only a couple.
Optimization 2: Don't allocate so many strings. Every call to
add_translationsallocates both for the key, and each individual inner pair too. Here is the body of theadd_translationsfunction:It's considered best practice to make your function signature clear. Usually, it's better to require a
Stringrather than&strif you're just going to.to_string()it in the function body.it also iterates over the entire passed
datato clone everything, and then creates another hashmap (thecollect)All of this was causing
stack overflowfor me on Windows. The expansion ofi18n!generated 14,000 HashMaps and spanned over 50,000 lines. With this PR, that's not an issue anymore.add_translationswas changed to this:Most inputs to it are static strings. There's no need to turn them into a
String, so they are passed asCow<'static, str>.I also added an
impl IntoIterator for SimpleBackend.The example expansion is located at
examples/app-egui/src/main.rsOld expansion
Note that then every of the
&'static stryou see will be.to_string()d in the function callNew expansion
This expansion both has way less overhead, and won't cause any stack overflows